package com.kexio.auth.web;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.kexio.auth.annotation.Audit;
import com.kexio.auth.annotation.RequiresPermission;

import cn.dev33.satoken.stp.StpUtil;
import jakarta.validation.constraints.NotBlank;

/**
 * Sa-Token令牌撤销管理控制器
 * 
 * 🔄 Sa-Token优化版本: 使用Sa-Token内置的撤销功能
 * 
 * 提供管理员手动撤销令牌的功能：
 * 1. 撤销单个用户登录 - 强制用户重新登录
 * 2. 撤销用户所有设备登录 - 全部设备下线
 * 3. 查询用户登录状态 - 监控和审计
 * 4. 批量管理用户会话 - 安全事件处理
 * 
 * 安全要求：
 * - 需要ADMIN权限或TOKEN_MANAGE权限
 * - 所有操作都会记录审计日志
 * - 支持跨租户管理（超级管理员）
 * 
 * @author Kexio Team
 * @since 2.1.0 - Sa-Token集成版本
 */
@RestController
@RequestMapping("/admin/tokens")
public class TokenRevocationController {
    
    private static final Logger logger = LoggerFactory.getLogger(TokenRevocationController.class);
    
    /**
     * 撤销单个用户登录
     * 
     * 🔄 Sa-Token优化: 使用Sa-Token内置的踢人下线功能
     * 
     * @param request 撤销请求
     * @return 撤销结果
     */
    @PostMapping("/revoke")
    @RequiresPermission("admin:token:revoke")
    public ResponseEntity<Map<String, Object>> revokeUserLogin(@RequestBody UserRevocationRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // Sa-Token踢人下线 (会清除该用户的所有token)
            StpUtil.kickout(request.getUserId());
            
            logger.warn("管理员撤销用户登录: adminUser={}, targetUser={}, tenantId={}, reason={}", 
                getCurrentUsername(), request.getUserId(), request.getTenantId(), request.getReason());
            
            result.put("success", true);
            result.put("message", "User login revoked successfully");
            result.put("details", Map.of(
                "userId", request.getUserId(),
                "tenantId", request.getTenantId() != null ? request.getTenantId() : "default",
                "reason", request.getReason(),
                "action", "kickout"
            ));
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            logger.error("撤销用户登录失败: userId={}, reason={}, error={}", 
                request.getUserId(), request.getReason(), e.getMessage(), e);
            
            result.put("success", false);
            result.put("message", "Failed to revoke user login: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }
    
    /**
     * 撤销用户的所有登录会话
     * 
     * 🔄 Sa-Token优化: 撤销指定用户的所有登录会话
     * 
     * @param request 用户撤销请求
     * @return 撤销结果
     */
    @PostMapping("/revoke-user")
    @RequiresPermission("admin:token:revoke-user")
    public ResponseEntity<Map<String, Object>> revokeUserAllSessions(@RequestBody UserRevocationRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // Sa-Token踢人下线 (已经是撤销所有会话)
            StpUtil.kickout(request.getUserId());
            
            logger.warn("管理员撤销用户所有会话: adminUser={}, targetUser={}, tenantId={}, reason={}", 
                getCurrentUsername(), request.getUserId(), request.getTenantId(), request.getReason());
            
            result.put("success", true);
            result.put("message", "All user sessions revoked successfully");
            result.put("details", Map.of(
                "userId", request.getUserId(),
                "tenantId", request.getTenantId() != null ? request.getTenantId() : "default",
                "reason", request.getReason(),
                "action", "kickout_all_sessions"
            ));
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            logger.error("撤销用户所有会话失败: userId={}, tenantId={}, reason={}, error={}", 
                request.getUserId(), request.getTenantId(), request.getReason(), e.getMessage(), e);
            
            result.put("success", false);
            result.put("message", "Failed to revoke user sessions: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }
    
    /**
     * 检查用户登录状态
     * 
     * 🔄 Sa-Token优化: 检查指定用户的登录状态
     * 
     * @param userId 用户ID
     * @return 检查结果
     */
    @GetMapping("/check")
    @RequiresPermission("admin:token:check")
    public ResponseEntity<Map<String, Object>> checkUserLoginStatus(@RequestParam String userId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // Sa-Token检查指定用户是否有会话 (通过尝试获取会话判断)
            boolean hasSession = false;
            try {
                hasSession = StpUtil.getSessionByLoginId(userId, false) != null;
            } catch (Exception e) {
                // 如果获取会话失败，说明用户未登录
                hasSession = false;
            }
            
            result.put("success", true);
            result.put("isLogin", hasSession);
            result.put("message", hasSession ? "User is currently logged in" : "User is not logged in");
            
            if (hasSession) {
                // 获取登录详细信息
                try {
                    long tokenTimeout = StpUtil.getTokenTimeout();
                    result.put("details", Map.of(
                        "userId", userId,
                        "hasSession", true,
                        "tokenTimeout", tokenTimeout > 0 ? tokenTimeout + "s" : "永不过期",
                        "sessionActive", true
                    ));
                } catch (Exception e) {
                    result.put("details", Map.of(
                        "userId", userId,
                        "hasSession", true,
                        "note", "会话存在但无法获取详细信息"
                    ));
                }
            } else {
                result.put("details", Map.of(
                    "userId", userId,
                    "hasSession", false,
                    "reason", "用户未登录或已被踢下线"
                ));
            }
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            logger.error("检查用户登录状态失败: userId={}, error={}", userId, e.getMessage());
            
            result.put("success", false);
            result.put("message", "Failed to check user login status: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }
    
    /**
     * 获取在线用户统计信息
     * 
     * 🔄 Sa-Token优化: 获取当前系统的在线用户统计
     * 
     * @return 统计信息
     */
    @GetMapping("/stats")
    @RequiresPermission("admin:token:stats")
    public ResponseEntity<Map<String, Object>> getOnlineUserStats() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // Sa-Token暂时不直接提供全局统计，返回基础信息
            result.put("success", true);
            result.put("message", "Online user statistics");
            result.put("stats", Map.of(
                "systemName", "Kexio Auth System",
                "version", "2.1.0-SaToken",
                "authFramework", "Sa-Token",
                "note", "Sa-Token不提供全局在线用户统计，可通过业务层实现"
            ));
            
            return ResponseEntity.ok(result);
            
        } catch (Exception e) {
            logger.error("获取在线用户统计失败: error={}", e.getMessage());
            
            result.put("success", false);
            result.put("message", "Failed to get online user stats: " + e.getMessage());
            return ResponseEntity.internalServerError().body(result);
        }
    }
    
    /**
     * 获取当前管理员用户名
     * 
     * 🔄 Sa-Token优化: 使用Sa-Token获取当前用户
     */
    private String getCurrentUsername() {
        try {
            if (StpUtil.isLogin()) {
                return StpUtil.getLoginIdAsString();
            }
        } catch (Exception e) {
            logger.debug("Sa-Token获取用户名失败: {}", e.getMessage());
        }
        return "unknown";
    }
    
    // ==================== 请求对象 ====================
    
    /**
     * 用户撤销请求 (Sa-Token优化版本)
     */
    public static class UserRevocationRequest {
        @NotBlank(message = "User ID is required")
        private String userId;
        
        private String tenantId = "default";
        private String reason = "Manual user revocation by admin";
        
        public String getUserId() { return userId; }
        public void setUserId(String userId) { this.userId = userId; }
        public String getTenantId() { return tenantId; }
        public void setTenantId(String tenantId) { this.tenantId = tenantId; }
        public String getReason() { return reason; }
        public void setReason(String reason) { this.reason = reason; }
    }
}
